# SPDX-License-Identifier: BSD-2-Clause

import os

from migen import *
from litex.gen import *

from litex.soc.interconnect.csr import *
from litex.soc.integration.doc import AutoDoc, ModuleDoc

# CRC_PCIE -----------------------------------------------------------------------------------------------------

class CRC(LiteXModule):

    def __init__(self, platform):
        self.intro = ModuleDoc("""Introduction

    Provides a generic CRC engine core.

    The CRC engine has 16bit text input and 32bit text output, which can be used in pcie

    ``load`` register bit load text input, write this bit will trigger one pulse.

    ``enable`` register bit enables crc calculation, after crc calculation enabled, you can read text output of crc calculation. 

    """)

        self._control = CSRStorage(description="CRC Control.", fields=[
            CSRField("load",   size=1, offset=0, pulse=True, description="CRC pulse load (Write ``1`` to load)."),
            CSRField("enable", size=1, offset=8,             description="CRC enable."),
        ])

        self._datain = CSRStorage(description="CRC Data input.", fields=[
            CSRField("text_in", size=16, offset=0,     description="CRC 16bit text input."),
        ])

        self._dataout = CSRStatus(description="CRC Data output.", fields=[
            CSRField("text_out", size=32,    description="CRC 32bit text output."),
        ])


        # # #

        # crc_top Verilog Core Instance.
        self.specials += Instance(self.get_netlist_name(),
            # Clk / Rst.
            i_clk    = ClockSignal("sys"),
            i_reset  = ResetSignal("sys"),
            # Crc Control.
            i_load   = self._control.fields.load,
            i_en     = self._control.fields.enable,
            i_din    = self._datain.fields.text_in,
            o_crc32n = self._dataout.fields.text_out,
        )

        self.add_sources(platform)


    def get_netlist_name(self):
        return "crc_top"

    def add_sources(self, platform):
        cdir = os.path.abspath('.')
        vdir = os.path.join(cdir, "CRC_PCIE", "sim")
        netlist_name = self.get_netlist_name()

        print(f"CRC_PCIE netlist : {netlist_name}")
        if not os.path.exists(os.path.join(vdir, netlist_name + ".v")):
            self.generate_netlist()

        platform.add_source(os.path.join(vdir,  netlist_name + ".v"), "verilog")

    def generate_netlist(self):
        print(f"Generating crc_top netlist")
        sources = []
        sdir = "CRC_PCIE"
        if not os.path.exists(sdir):
            os.system(f"git clone git://repogit.moditek/crc_pcie.git CRC_PCIE")

        cdir = os.path.abspath('.')

        cmd = 'cd {path} && bash merge_rtl.cmd'.format(
            path=os.path.join(cdir, "CRC_PCIE", "sim") )
        print("!!! "   + cmd)
        if os.system(cmd) != 0:
            raise OSError('Failed to run merge_rtl.cmd')

